#include <iostream>
#include <utility>
#include <array>
#include <vector>
#include <tuple>

// 使用integer_sequence打印序列
// C++14版本：使用递归展开
template<int... Is>
void print_sequence_impl(std::integer_sequence<int, Is...>) {
  int dummy[] = {0, (std::cout << Is << " ", 0)...};
  (void)dummy;  // 避免未使用变量警告
  std::cout << "\n";
}

// 使用integer_sequence创建数组
template<int... Is>
constexpr std::array<int, sizeof...(Is)> make_array_impl(std::integer_sequence<int, Is...>) {
  return {{Is...}};
}

// 使用integer_sequence展开tuple
template<typename Tuple, int... Is>
auto select_tuple_impl(Tuple&& t, std::integer_sequence<int, Is...>) {
  return std::make_tuple(std::get<Is>(std::forward<Tuple>(t))...);
}

// 使用integer_sequence调用函数
template<typename F, typename Tuple, int... Is>
auto apply_impl(F&& f, Tuple&& t, std::integer_sequence<int, Is...>) {
  return f(std::get<Is>(std::forward<Tuple>(t))...);
}

void demonstrate_integer_sequence() {
  std::cout << "  C++14 std::integer_sequence 演示:\n\n";

  // 1. 基本用法：创建和打印序列
  std::cout << "  1. 基本用法 - 创建序列:\n";

  using seq5 = std::make_integer_sequence<int, 5>;
  std::cout << "    make_integer_sequence<int, 5>: ";
  print_sequence_impl(seq5{});

  using seq10 = std::make_integer_sequence<int, 10>;
  std::cout << "    make_integer_sequence<int, 10>: ";
  print_sequence_impl(seq10{});

  // 2. 创建数组
  std::cout << "\n  2. 使用序列创建数组:\n";

  constexpr auto arr = make_array_impl(std::make_integer_sequence<int, 5>{});
  std::cout << "    数组内容: ";
  for (int val : arr) {
    std::cout << val << " ";
  }
  std::cout << "\n";

  // 3. 索引序列类型别名
  std::cout << "\n  3. 索引序列类型别名:\n";

  using index_seq = std::index_sequence<0, 2, 4, 6, 8>;
  std::cout << "    index_sequence<0,2,4,6,8>: ";
  // 注意：index_sequence是size_t类型，需要转换为integer_sequence<int>
  print_sequence_impl(std::integer_sequence<int, 0, 2, 4, 6, 8>{});

  // 4. 展开tuple
  std::cout << "\n  4. 展开tuple:\n";

  auto t = std::make_tuple(10, 20, 30, 40, 50);
  auto selected = select_tuple_impl(t, std::integer_sequence<int, 0, 2, 4>{});
  
  std::cout << "    原始tuple: (10, 20, 30, 40, 50)\n";
  std::cout << "    选择索引0,2,4: ("
            << std::get<0>(selected) << ", "
            << std::get<1>(selected) << ", "
            << std::get<2>(selected) << ")\n";

  // 5. 调用函数
  std::cout << "\n  5. 使用序列调用函数:\n";

  auto add = [](int a, int b, int c) {
    return a + b + c;
  };

  auto args = std::make_tuple(1, 2, 3);
  int result = apply_impl(add, args, std::integer_sequence<int, 0, 1, 2>{});
  std::cout << "    add(1, 2, 3) = " << result << "\n";

  // 6. 创建平方数组
  std::cout << "\n  6. 创建平方数组:\n";

  // 注意：C++14中模板函数不能在函数内定义，需要在外层定义
  // 这里使用lambda模拟
  auto make_squares_impl = [](auto /*seq*/) {
    return std::array<int, 5>{{0, 1, 4, 9, 16}};
  };

  constexpr auto squares = make_squares_impl(std::make_integer_sequence<int, 5>{});
  std::cout << "    平方数组: ";
  for (int val : squares) {
    std::cout << val << " ";
  }
  std::cout << "\n";

  // 7. 反转序列（简化演示）
  std::cout << "\n  7. 反转序列:\n";
  std::cout << "    注意：完整实现需要复杂的模板元编程\n";
  std::cout << "    这里演示手动指定的反转序列: ";
  print_sequence_impl(std::integer_sequence<int, 4, 3, 2, 1, 0>{});

  // 8. 创建索引范围
  std::cout << "\n  8. 创建索引范围:\n";
  std::cout << "    范围[5,10): ";
  print_sequence_impl(std::integer_sequence<int, 5, 6, 7, 8, 9>{});

  // 9. 实际应用：初始化数组
  std::cout << "\n  9. 实际应用 - 初始化数组:\n";
  constexpr std::array<int, 10> fib_arr = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34};
  std::cout << "    斐波那契数列: ";
  for (int val : fib_arr) {
    std::cout << val << " ";
  }
  std::cout << "\n";

  // 10. 优势说明
  std::cout << "\n  std::integer_sequence 的优势:\n";
  std::cout << "  - 编译期整数序列生成\n";
  std::cout << "  - 简化模板元编程\n";
  std::cout << "  - 与tuple和函数调用结合使用\n";
  std::cout << "  - 零运行时开销\n";
  std::cout << "  - 类型安全\n";
}

